#include "base/file.h"

#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#include <fstream>
#include <iostream>

File::File() {}

File::~File() {}

void File::WriteBinaryToFile(
    const std::string& file_name, unsigned char* data, int length) {
  std::ofstream out(file_name.c_str(), std::ios::out | std::ios::binary);
  out.write(reinterpret_cast<char*>(data), length);
  out.close();
}

void File::AppendBinaryToFile(
    const std::string& file_name, unsigned char* data, int length) {
  std::ofstream out(file_name.c_str(), std::ios::out | std::ios::binary);
  out.write(reinterpret_cast<char*>(data), length);
  out.close();
}

bool File::AppendDataToFile(
    const std::string& file_name, const std::string& data, bool line_break) {
  std::ofstream out(file_name.c_str(), std::ios::app);
  out.write(reinterpret_cast<const char*>(data.c_str()), data.length());
  if (line_break) {
    out << std::endl;
  }
  out.close();
  return true;
}

bool File::ReadFileToVector(
    const std::string& file_name, std::vector<std::string>* vec) {
  if (vec == nullptr) return false;
  std::ifstream infile(file_name.data(), std::ios::in);
  if (!infile.is_open()) return false;
  std::string s;
  while (getline(infile, s)) {
    vec->push_back(s);
  }
  infile.close();
  return true;
}

bool File::ReadFileToVector(
    const std::string& file_name,
    std::vector<std::vector<std::string> >* res,
    const std::string& pattern) {
  if (res == nullptr) return false;
  std::ifstream infile(file_name.data(), std::ios::in);
  if (!infile.is_open()) return false;
  std::string s;
  while (getline(infile, s)) {
    res->push_back(SplitString(s, pattern));
  }
  infile.close();
  return true;
}

bool File::ReadFileToList(
    const std::string& file_name, std::list<std::string>* res) {
  if (res == nullptr) return false;
  std::ifstream infile(file_name.data(), std::ios::in);
  if (!infile.is_open()) return false;
  std::string s;
  while (getline(infile, s)) {
    res->push_back(s);
  }
  infile.close();
  return true;
}

bool File::ReadFileToList(
    const std::string& file_name,
    std::list<std::vector<std::string> >* res,
    const std::string& pattern) {
  if (res == nullptr) return false;
  std::ifstream infile(file_name.data(), std::ios::in);
  if (!infile.is_open()) return false;
  std::string s;
  while (getline(infile, s)) {
    res->push_back(SplitString(s, pattern));
  }
  infile.close();
  return true;
}

bool File::Exist(const std::string& path) {
  if (path.empty()) return false;
  return (::access(path.c_str(), 0)) != -1;
}

bool File::CreateDirectory(const std::string& path) {
  if (path.empty()) return false;
  if (Exist(path)) return true;
  return ::mkdir(path.c_str(), 0755) == 0;
}

std::string File::GetFileName(const std::string& path) {
  std::size_t index = path.find_last_of("/\\");
  return path.substr(index + 1);
}

std::vector<std::string> File::SplitString(
    const std::string& str, const std::string& pattern) {
  std::string::size_type pos;
  std::vector<std::string> result;

  std::string s = TrimString(str);
  while ((pos = s.find(pattern)) != std::string::npos) {
    std::string tmp = s.substr(0, pos);
    result.push_back(tmp);
    s = TrimString(s.substr(pos + 1, s.size() - pos));
    if(s.compare(pattern) == 0) {
      result.push_back("");
      break;
    }
  }

  if (s != "") {
    result.push_back(s);
  }

  return result;
}

std::string File::TrimString(const std::string& s) {
  if (s == "") return "";
  std::string str = s;
  while (str[0] == ' ') {
    str = str.substr(1, str.size() - 1);
  }

  while (str[str.size() - 1] == ' ') {
    str = str.substr(0, str.size() - 1);
  }

  return str;
}

